#include "mqtt_manager.h"

#include "esp_task_manager.h"
#include "app.h"
#include "settings.h"
#include "board.h"
#include "config.h"
#include "system_info.h"

#define TAG "MqttManager"

MqttManager::MqttManager() {
    task_executor_ = TaskManager::GetInstance().CreateExecutor("mqtt_manager", 8192, 8, 0);
    ESP_LOGI(TAG, "MQTT管理器初始化");
}

MqttManager::~MqttManager() {
    ESP_LOGI(TAG, "MQTT管理器销毁");
    
    //清理MQTT客户端
    mqtt_.reset();
    
    // 清理订阅跟踪信息
    {
        std::lock_guard<std::mutex> lock(callbacks_mutex_);
        subscribed_topics_.clear();
        realtime_callbacks_.clear();
        standard_callbacks_.clear();
    }
}


bool MqttManager::start() {
    ESP_LOGI(TAG, "启动MQTT管理器");
    auto& app = App::GetInstance();
    app.SetDeviceState(kDeviceStateMqttConnecting);
    if (mqtt_ != nullptr) {
        ESP_LOGW(TAG, "MQTT客户端已存在，重新初始化");
        mqtt_.reset();
    }
    // 初始化MQTT客户端
    mqtt_ = std::make_unique<EspMqttImpl>();

    config_.broker_url = MQTT_BROKER_URL;
    config_.port = MQTT_PORT;
    config_.client_id = MQTT_CLIENT_ID;
    config_.username = MQTT_USERNAME;
    config_.password = MQTT_PASSWORD;

    ESP_LOGI(TAG, "MQTT配置: %s, 客户端ID: %s", 
              config_.broker_url.c_str(), config_.client_id.c_str());

    if(config_.broker_url.empty() || config_.client_id.empty()){
        ESP_LOGE(TAG, "MQTT配置错误: broker_url 或 client_id 为空");
        return false;
    }
    
    mqtt_->SetKeepAlive(config_.keep_alive_seconds);//设置保活时间
    
    // 设置消息回调处理函数
    mqtt_->OnMessage([this](const std::string& topic, const std::string& payload) {
        this->OnMessageReceived(topic, payload);
    });
    mqtt_->OnConnected([this]() {
        ESP_LOGI(TAG, "MQTT连接成功");
        App::GetInstance().SetDeviceState(kDeviceStateMqttOk);
        Board::GetInstance().StartOta();//连接了MQTT，证明有网了，尝试OTA
        this->OnConnected();
    });
    mqtt_->OnDisconnected([]() {
        ESP_LOGE(TAG, "MQTT连接断开");
        App::GetInstance().SetDeviceState(kDeviceStateMqttError);
    });
    
    if (!mqtt_->Connect(config_.broker_url, config_.port, config_.client_id,config_.username,config_.password)) {
        ESP_LOGE(TAG, "MQTT连接失败");
        app.SetDeviceState(kDeviceStateMqttError);
        return false;
    }
    
    app.SetDeviceState(kDeviceStateMqttOk);
    return true;
}

bool MqttManager::SubscribeRealtime(const char* topic, int qos, mqtt_fast_callback_t callback, void* user_data) {
    if (!callback) {
        ESP_LOGE(TAG, "回调函数为空，无法订阅: %s", topic);
        return false;
    }

    ESP_LOGI(TAG, "订阅实时主题: %s", topic);

    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    
    // 添加回调到实时回调列表（不管MQTT是否连接都要记录）
    RealtimeCallback rt_callback = {callback, user_data};
    realtime_callbacks_[std::string(topic)].push_back(rt_callback);

    // 记录订阅信息用于重连时重新订阅（不管MQTT是否连接都要记录）
    subscribed_topics_[std::string(topic)] = qos;

    // 如果MQTT已连接，尝试立即订阅
    if (mqtt_ && mqtt_->IsConnected()) {
        if (!mqtt_->Subscribe(std::string(topic), qos)) {
            ESP_LOGW(TAG, "订阅失败，将在重连后自动订阅: %s", topic);
        }
    } else {
        ESP_LOGW(TAG, "MQTT未连接，连接后自动订阅: %s", topic);
    }

    return true;  // 总是返回true，除非参数错误
}

bool MqttManager::Subscribe(const std::string& topic, int qos, MqttCallback callback) {
    if (!callback) {
        ESP_LOGE(TAG, "回调函数为空，无法订阅: %s", topic.c_str());
        return false;
    }

    ESP_LOGI(TAG, "订阅标准主题: %s", topic.c_str());

    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    
    // 添加回调到标准回调列表（不管MQTT是否连接都要记录）
    standard_callbacks_[topic].push_back(callback);

    // 记录订阅信息用于重连时重新订阅（不管MQTT是否连接都要记录）
    subscribed_topics_[topic] = qos;

    // 如果MQTT已连接，尝试立即订阅
    if (mqtt_ && mqtt_->IsConnected()) {
        if (!mqtt_->Subscribe(topic, qos)) {
            ESP_LOGW(TAG, "订阅失败，将在重连后自动订阅: %s", topic.c_str());
        }
    } else {
        ESP_LOGW(TAG, "MQTT未连接，连接后自动订阅: %s", topic.c_str());
    }

    return true;  // 总是返回true，除非参数错误
}

bool MqttManager::Unsubscribe(const std::string& topic) {
    std::lock_guard<std::mutex> lock(callbacks_mutex_);

    // 先清理订阅记录和回调函数（不管MQTT是否连接都要清理）
    standard_callbacks_.erase(topic);
    subscribed_topics_.erase(topic);

    // 如果MQTT已连接，尝试取消MQTT订阅
    if (mqtt_ && mqtt_->IsConnected()) {
        if (!mqtt_->Unsubscribe(topic)) {
            ESP_LOGW(TAG, "取消订阅失败，但已清理本地记录: %s", topic.c_str());
        } else {
            ESP_LOGI(TAG, "取消订阅成功: %s", topic.c_str());
        }
    }

    return true;  // 总是返回true，因为本地清理总是成功的
}

bool MqttManager::UnsubscribeRealtime(const char* topic) {
    std::lock_guard<std::mutex> lock(callbacks_mutex_);

    // 先清理订阅记录和回调函数（不管MQTT是否连接都要清理）
    realtime_callbacks_.erase(std::string(topic));
    subscribed_topics_.erase(std::string(topic));

    // 如果MQTT已连接，尝试取消MQTT订阅
    if (mqtt_ && mqtt_->IsConnected()) {
        if (!mqtt_->Unsubscribe(std::string(topic))) {
            ESP_LOGW(TAG, "取消订阅失败，但已清理本地记录: %s", topic);
        } else {
            ESP_LOGI(TAG, "取消订阅成功: %s", topic);
        }
    }

    return true;  // 总是返回true，因为本地清理总是成功的
}

void MqttManager::OnMessageReceived(const std::string& topic, const std::string& payload) {
    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    
    // 先处理高性能实时回调（C风格，零拷贝）
    auto realtime_it = realtime_callbacks_.find(topic);
    if (realtime_it != realtime_callbacks_.end()) {
        const char* topic_cstr = topic.c_str();
        const char* payload_cstr = payload.c_str();
        size_t payload_length = payload.length();
        
        for (const auto& rt_callback : realtime_it->second) {
            if (rt_callback.callback) {
                // 直接调用C风格回调，性能最高
                rt_callback.callback(topic_cstr, payload_cstr, payload_length, rt_callback.user_data);
            }
        }
    }
    
    // 再处理标准回调（C++风格，有额外的string拷贝开销）
    auto standard_it = standard_callbacks_.find(topic);
    if (standard_it != standard_callbacks_.end()) {
        for (const auto& std_callback : standard_it->second) {
            if (std_callback) {
                // C++ std::function调用，有额外开销
                std_callback(topic, payload);
            }
        }
    }
}

void MqttManager::OnConnected() {
    ESP_LOGI(TAG, "重新订阅主题，总计: %zu 个", subscribed_topics_.size());
    
    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    
    // 重新订阅所有之前订阅的主题
    for (const auto& topic_qos : subscribed_topics_) {
        const std::string& topic = topic_qos.first;
        int qos = topic_qos.second;
        
        if (!mqtt_->Subscribe(topic, qos)) {
            ESP_LOGE(TAG, "重新订阅失败: %s", topic.c_str());
        }
    }
}

// ================== 发布方法实现 ==================

bool MqttManager::Publish(const std::string& topic, const std::string& payload, int qos, bool retain) {
    if (!mqtt_ || !mqtt_->IsConnected()) {
        ESP_LOGE(TAG, "MQTT未连接，无法发布: %s", topic.c_str());
        return false;
    }

    if (topic.empty()) {
        ESP_LOGE(TAG, "主题为空，无法发布");
        return false;
    }

    bool result = mqtt_->Publish(topic, payload, qos);
    
    if (!result) {
        ESP_LOGE(TAG, "发布失败: %s", topic.c_str());
    }
    
    return result;
}

bool MqttManager::PublishAsync(const std::string& topic, const std::string& payload, int qos, bool retain, PublishCallback callback) {
    //使用任务管理器，进行异步发布
    task_executor_->AddTask([this, topic, payload, qos, retain, callback]() {
      bool result = Publish(topic, payload, qos, retain);
      // 如果提供了回调，立即调用
      if (callback) {
          callback(result);
      }
    },TaskType::IMMEDIATE,TaskPriority::TASKNORMAL,"mqtt_publish");
    return true;
}

bool MqttManager::IsConnected() const {
    return mqtt_ && mqtt_->IsConnected();
}
